package com.yeyi.ytest;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;

/**
 * 基础类
 * 
 * @author: yeyi
 * @date: 2019年3月22日
 */
public class BaseController {

    private Logger loggerBase = LoggerFactory.getLogger(this.getClass());
    
    // 请求后缀
 	public static final String SUFFIX = ".do";

 	// 默认第几页
 	protected static final Integer DEFAULT_PAGE = 1;

 	// 默认每页多少条
 	protected static final Integer DEFAULT_ROWS = 10;

 	private static final String CODE = "code";
 	private static final String MSG = "msg";
 	private static final String ROWS = "rows";
 	private static final String TOTAL = "total";
 	private static final String DATA = "data";
 
 	// inputStream 放到 attribute 中的 key
 	private static final String INPUT_STREAM_KEY = "inputStreamKey";
    
    /**
	 * 返回 标准错误信息
	 * @param msg 错误信息
	 * @return
	 * @author: yeyi
	 * @date: 2018年12月26日
	 */
	protected Map<String, Object> returnError(String msg) {
		Map<String, Object> result = this.returnError();
		result.put(MSG, msg);
		return result;
	}

	protected Map<String, Object> returnError(String code, String msg) {
		Map<String, Object> result = this.returnError();
		result.put(CODE, code);
		result.put(MSG, msg);
		return result;
	}

	protected Map<String, Object> returnError() {
		Map<String, Object> result = new HashMap<>();
		result.put(CODE, "ERROR_BOSS");
		result.put(MSG, "系统错误,请联系管理员");
		return result;
	}

	/**
	 * 返回标准成功信息
	 * @return
	 * @author: yeyi
	 * @date: 2018年12月26日
	 */
	protected Map<String, Object> returnSuccess() {
		Map<String, Object> result = new HashMap<>();
		result.put(CODE, "0000");
		result.put(MSG, "提交成功");
		return result;
	}

	protected Map<String, Object> returnSuccessMsg(String msg) {
		Map<String, Object> result = this.returnSuccess();
		result.put(MSG, msg);
		return result;
	}

	protected Map<String, Object> returnSuccessRows(Object rows, Long total) {
		Map<String, Object> result = this.returnSuccess();
		result.put(ROWS, rows);
		result.put(TOTAL, total);
		return result;
	}

	protected Map<String, Object> returnSuccessRows(Object rows, Integer total) {
		Map<String, Object> result = this.returnSuccess();
		result.put(ROWS, rows);
		result.put(TOTAL, total);
		return result;
	}
	
	protected Map<String, Object> returnSuccessData(Object data) {
		Map<String, Object> result = this.returnSuccess();
		result.put(DATA, data);
		return result;
	}
	
	/**
	 * 要重新登录的异常
	 * 
	 * @author: yeyi
	 * @date: 2019年3月22日
	 */
	class NeedLoginException extends RuntimeException {

		/**
		 * serialVersionUID
		 */
		private static final long serialVersionUID = 3456790518117831517L;

	}
	
	@ExceptionHandler(NeedLoginException.class)
	@ResponseBody
	public Map<String, Object> handleNeedLoginException(NeedLoginException ex) {
		return returnError("请登录");
	}
	
	/**
	 * 从 request 中取参数，如果普通参数没有则取 json 参数，并缓存一份 imputStream 到 attribute 中让下次还可以取
	 * @param request
	 * @param name
	 * @return 出错或找不到返回 null
	 * @author: yeyi
	 * @date: 2019年3月28日
	 */
	protected String getParameter(HttpServletRequest request, String name) {
		String result = request.getParameter(name);
		if(null!=result) {
			return result;
		}
		
		String contentType = request.getContentType();
		// 不是 json 直接返回空
		if(!contentType.toLowerCase().contains("application/json")) {
			return null;
		}
		
		// 已存在直接拿
		try {
			byte [] bytes = (byte[])request.getAttribute(INPUT_STREAM_KEY);
			if(null!=bytes) {
				return this.getParamFromBytes(bytes, name);
			}
		} catch (Exception e) {
			loggerBase.error("getParamete getAttribute err: ", e);
			return null;
		}
		
		// 不存在从流中拿
		try {
			byte [] bytes = IOUtils.toByteArray(request.getInputStream());
			request.setAttribute(INPUT_STREAM_KEY, bytes);
			return this.getParamFromBytes(bytes, name);
		} catch (Exception e) {
			loggerBase.error("request.getInputStrea err: ", e);
			return null;
		}
	}
	
	private String getParamFromBytes(byte [] bytes, String name) {
		String body = new String(bytes);
		if(StringUtils.isBlank(body)) {
			return null;
		}
		JSONObject jb = JSONObject.parseObject(body);
		return jb.getString(name);
	}
}
